package com.rongmei.jdsync.dto.sync;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.Builder;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 价格同步结果统计
 *
 * @author dongjun
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(description = "价格同步结果统计")
public class PriceSyncResult {

    @Schema(description = "同步批次ID", example = "SYNC_20231201120000")
    private String syncBatchId;

    @Schema(description = "需要同步的商品总数", example = "50")
    private int totalSyncGoods;

    @Schema(description = "本地找到的商品数", example = "950")
    private int localFoundGoods;

    @Schema(description = "价格有变更的商品数", example = "85")
    private int priceChangedGoods;

    @Schema(description = "推送成功的商品数", example = "80")
    private int pushSuccessGoods;

    @Schema(description = "推送失败的商品数", example = "5")
    private int pushFailedGoods;

    @Schema(description = "执行耗时（毫秒）", example = "15000")
    private long executionTime;

    @Schema(description = "总价格变更金额", example = "1250.50")
    private BigDecimal totalChangeAmount;

    @Schema(description = "同步状态：SUCCESS-成功，PARTIAL_SUCCESS-部分成功，FAILED-失败，NO_CHANGE-无变更")
    private SyncStatus status;

    @Schema(description = "同步开始时间")
    private LocalDateTime startTime;

    @Schema(description = "同步结束时间")
    private LocalDateTime endTime;

    @Schema(description = "错误信息")
    private String errorMessage;

    @Schema(description = "同步配置快照")
    private SyncOptions syncOptions;

    /**
     * 同步状态枚举
     */
    public enum SyncStatus {
        SUCCESS,         // 全部成功
        PARTIAL_SUCCESS, // 部分成功
        FAILED,          // 全部失败
        NO_CHANGE        // 无变更
    }

    /**
     * 创建成功结果
     */
    public static PriceSyncResult success(String syncBatchId, int totalGoods, int localFound, 
                                        int priceChanged, int pushSuccess, long executionTime) {
        return PriceSyncResult.builder()
                .syncBatchId(syncBatchId)
                .totalSyncGoods(totalGoods)
                .localFoundGoods(localFound)
                .priceChangedGoods(priceChanged)
                .pushSuccessGoods(pushSuccess)
                .pushFailedGoods(0)
                .executionTime(executionTime)
                .status(priceChanged == 0 ? SyncStatus.NO_CHANGE : SyncStatus.SUCCESS)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * 创建部分成功结果
     */
    public static PriceSyncResult partialSuccess(String syncBatchId, int totalGoods, int localFound,
                                               int priceChanged, int pushSuccess, int pushFailed, 
                                               long executionTime) {
        return PriceSyncResult.builder()
                .syncBatchId(syncBatchId)
                .totalSyncGoods(totalGoods)
                .localFoundGoods(localFound)
                .priceChangedGoods(priceChanged)
                .pushSuccessGoods(pushSuccess)
                .pushFailedGoods(pushFailed)
                .executionTime(executionTime)
                .status(SyncStatus.PARTIAL_SUCCESS)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * 创建失败结果
     */
    public static PriceSyncResult failure(String syncBatchId, String errorMessage, long executionTime) {
        return PriceSyncResult.builder()
                .syncBatchId(syncBatchId)
                .totalSyncGoods(0)
                .localFoundGoods(0)
                .priceChangedGoods(0)
                .pushSuccessGoods(0)
                .pushFailedGoods(0)
                .executionTime(executionTime)
                .status(SyncStatus.FAILED)
                .errorMessage(errorMessage)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * 创建无变更结果
     */
    public static PriceSyncResult noChange(String syncBatchId, int totalGoods, int localFound, 
                                         long executionTime) {
        return PriceSyncResult.builder()
                .syncBatchId(syncBatchId)
                .totalSyncGoods(totalGoods)
                .localFoundGoods(localFound)
                .priceChangedGoods(0)
                .pushSuccessGoods(0)
                .pushFailedGoods(0)
                .executionTime(executionTime)
                .status(SyncStatus.NO_CHANGE)
                .endTime(LocalDateTime.now())
                .build();
    }

    /**
     * 计算成功率
     */
    public double getSuccessRate() {
        if (priceChangedGoods == 0) {
            return 1.0;
        }
        return (double) pushSuccessGoods / priceChangedGoods;
    }

    /**
     * 计算本地商品找到率
     */
    public double getLocalFoundRate() {
        if (totalSyncGoods == 0) {
            return 1.0;
        }
        return (double) localFoundGoods / totalSyncGoods;
    }

    /**
     * 计算价格变更率
     */
    public double getPriceChangeRate() {
        if (localFoundGoods == 0) {
            return 0.0;
        }
        return (double) priceChangedGoods / localFoundGoods;
    }

    /**
     * 是否执行成功
     */
    public boolean isSuccess() {
        return status == SyncStatus.SUCCESS || status == SyncStatus.NO_CHANGE;
    }

    /**
     * 是否有错误
     */
    public boolean hasError() {
        return status == SyncStatus.FAILED || pushFailedGoods > 0;
    }

    /**
     * 设置同步开始时间
     */
    public PriceSyncResult markStart() {
        this.startTime = LocalDateTime.now();
        return this;
    }

    /**
     * 设置同步结束时间并计算耗时
     */
    public PriceSyncResult markEnd() {
        this.endTime = LocalDateTime.now();
        if (this.startTime != null) {
            this.executionTime = java.time.Duration.between(startTime, endTime).toMillis();
        }
        return this;
    }

    /**
     * 自动设置状态
     */
    public PriceSyncResult autoSetStatus() {
        if (priceChangedGoods == 0) {
            this.status = SyncStatus.NO_CHANGE;
        } else if (pushFailedGoods == 0) {
            this.status = SyncStatus.SUCCESS;
        } else if (pushSuccessGoods > 0) {
            this.status = SyncStatus.PARTIAL_SUCCESS;
        } else {
            this.status = SyncStatus.FAILED;
        }
        return this;
    }

    @Override
    public String toString() {
        return String.format("价格同步结果[%s]: 需要同步[%d], 本地找到[%d], 价格变更[%d], 推送成功[%d], 推送失败[%d], 成功率[%.2f%%], 耗时[%dms], 状态[%s]",
                syncBatchId, 
                Integer.valueOf(totalSyncGoods), 
                Integer.valueOf(localFoundGoods), 
                Integer.valueOf(priceChangedGoods), 
                Integer.valueOf(pushSuccessGoods), 
                Integer.valueOf(pushFailedGoods), 
                Double.valueOf(getSuccessRate() * 100), 
                Long.valueOf(executionTime), 
                status.toString());
    }
}